<?php
/**
 * Created by PhpStorm.
 * User: 69548
 * Date: 2018/7/31
 * Time: 14:34
 */

namespace app\api\controller;


use app\common\controller\Api;
use app\api\controller\KbxToken;
use app\api\controller\Common;
use think\Controller;
use think\Cache;
use think\Session;
use app\api\model\GroupToursLine as GT;
use app\api\controller\Member as MApi;
use app\common\controller\Token as UserToken;

class Unionid extends Api
{
    //使用trait方法复用
    use UserToken;
    /**
     * error code 说明.
     * <ul>
     *    <li>-41001: encodingAesKey 非法</li>
     *    <li>-41003: aes 解密失败</li>
     *    <li>-41004: 解密后得到的buffer非法</li>
     *    <li>-41005: base64加密失败</li>
     *    <li>-41016: base64解密失败</li>
     * </ul>
     */
    public  $OK = 0;
    public  $IllegalAesKey = -41001;
    public  $IllegalIv = -41002;
    public  $IllegalBuffer = -41003;
    public  $DecodeBase64Error = -41004;
    private $appid;
    private $appsecret;
    private $isHyaline = true;
    //前置方法 验证token only后是需要执行前置的方法 所有字母必须小写 'only'=>’xxx,yyy,zzz‘
    protected $beforeActionList = [
//        'checkSign'=>[
//            'only'=>'refreshusertoken'
//        ]

    ];

    //获取拼游小程序配置
    protected function getTourInfo()
    {
        return [
            'appid'=>config('WxConfig.gtour')['appid'],
            'secret'=>config('WxConfig.gtour')['appsecret'],
        ];
    }
    //获取北美玩乐小程序配置
    protected function getBeimeiInfo()
    {
        return [
            'appid'=>config('WxConfig.beimei')['appid'],
            'secret'=>config('WxConfig.beimei')['appsecret'],
        ];
    }
    /**
     *  获取用户的信息 【用户存在更新小程序openid，不存在就新增用户信息】
     */
    public function index()
    {
        $code = input('code');//小程序的code 用于获取openid,unionid,session_key
        $wxsoft = input('wxsoft','beimei');
        if(!in_array($wxsoft,['grouptour','beimei'])) return json_encode(['code'=>-101,'msg'=>'请求不合法']);
        if($wxsoft=='grouptour'){//拼游
            $wxsoft_config = $this->getTourInfo();
            $field_name = 'grouptour_openid';
        }else{
            $wxsoft_config = $this->getBeimeiInfo();
            $field_name = 'program_openid';
        }
        $this->appid = $wxsoft_config['appid'];
        $this->appsecret = $wxsoft_config['secret'];
        $field_token_name = $wxsoft.'_token';
        $url='https://api.weixin.qq.com/sns/jscode2session?appid='.$this->appid.'&secret='.$this->appsecret.'&js_code='.$code.'&grant_type=authorization_code';
        trace('微信授权地址：'.$url);
        list($sessionKey,$decryptDataArr) = $this->getDecrptdData($url);
        if(!is_array($decryptDataArr)){
            return json_encode(['code'=>$decryptDataArr,'msg'=>'授权失败']);
        }elseif($sessionKey==''){
            return json_encode(['code'=>$decryptDataArr['errcode'],'msg'=>$decryptDataArr['errmsg']]);
        }
        trace('微信授权数据:'.json_encode($decryptDataArr));
        //dump($decryptDataArr);exit;
        //获取unionid
        $unionid = $decryptDataArr['unionid']??$decryptDataArr['unionId'];
        $openid = $decryptDataArr['openid']??$decryptDataArr['openId'];

        //获取用户信息
        $member = db('member')->where('wechat_unionid',$unionid)->find();
        Session::set('uid',$member['member_id']);

        if(empty($member)){
            $res = db('member')->insert([
                'member_nickname'   => $decryptDataArr['nickName'],
                'wechat_unionid'    => $unionid,
                $field_name         => $openid,
                'thumb'             => db('attachment')->insertGetId(['filepath'=>$decryptDataArr['avatarUrl']]),
                'creattime'         => time(),
                'member_city'       => $decryptDataArr['city']
            ]);
            if (empty($res)){
                $data = [
                    'code'=>101,
                    'msg'=>'数据写入错误！ 授权失败'
                ];
                return json_encode($data);
            }
            //获取用户id
            $member_id = db()->getLastInsID();
            //同步账号信息
            $updateData = [
                'wechat'=>[
                    'unionidOA'=>$unionid
                ],
                'thumb'=>$decryptDataArr['avatarUrl'],
                'nickname'=>$decryptDataArr['nickName'],
                'origin'=>'customizeApp'
            ];
        }else{
            //更新用户的头像信息
            //如果用户头像是oss则不更新
            $update_thumb = true;
            if(!empty($member['thumb'])){
                $headimg = db('attachment')->where('id',$member['thumb'])->find();
                if(!empty($headimg) && strpos($headimg['filepath'],'i.kuaibangxing.com')!==false){
                    $update_thumb = false;
                }
            }
            if($update_thumb){
                $thumb = db('attachment')->insertGetId(['filepath'=>$decryptDataArr['avatarUrl']]);
                db('member')->where('member_id',$member['member_id'])->update(['thumb'=>$thumb]);
                $member['thumb'] = $thumb;
            }
            if (empty($member[$field_name])){
                $res = db('member')
                    ->where('wechat_unionid',$unionid)
                    ->update([
                        $field_name=>$openid
                    ]);
                if ($res===false){
                    $data = [
                        'code'=>101,
                        'msg'=>'数据写入错误！ 授权失败'
                    ];
                    return json_encode($data);
                }
            }
            $member_id = $member['member_id'];
            //同步账号信息
            $updateData = [
                'wechat'=>[
                    'unionidOA'=>$unionid
                ],
                'thumb'=>db('attachment')->find($member['thumb'])['filepath'],
                'nickname'=>$member['member_nickname'],
                'origin'=>'customizeApp'
            ];
            if(!empty($member['member_phone'])){
                $updateData['username'] = $member['member_phone'];
            }
        }
        $this->syncUserDataToOrderSystem($member_id,$updateData);
        //更新用户的token
        $userToken = $this->updateUserToken($member_id,$field_token_name);
        if(empty($userToken)){
            $data = [
                'code'=>101,
                'msg'=>'获取userToken失败！ 授权失败'
            ];
            return json_encode($data);
        }
        //更新kbx之后的数据
        $member = db('member')->find($member_id);
        //返回授权数据
        $data = [
            'code'=>0,
            'msg'=>'授权成功',
            'data'=>[
                'openId'=>$openid,
                'unionId'=>$unionid,
                'sessionKey'=>$sessionKey,
                'userToken'=>$userToken,
                'userKbxId'=>$member['kbx_id']
            ]
        ];

        return json_encode($data);
    }

    /**
     * 检验数据的真实性，并且获取解密后的明文.
     * @param $encryptedData string 加密的用户数据
     * @param $iv string 与用户数据一同返回的初始向量
     * @param $data string 解密后的原文
     *
     * @return int 成功0，失败返回对应的错误码
     */
    protected function decryptData( $encryptedData, $iv, &$data , $appid, $sessionKey)
    {
        if (strlen($sessionKey) != 24){
            return $this->IllegalAesKey;
        }
        $aesKey=base64_decode($sessionKey);
        if (strlen($iv) != 24) {
            return $this->IllegalIv;
        }
        $aesIV=base64_decode($iv);

        $aesCipher=base64_decode($encryptedData);

        $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
        $dataObj=json_decode( $result );
        if( $dataObj  == NULL )
        {
            return $this->IllegalBuffer;
        }
        if( $dataObj->watermark->appid != $appid )
        {
            return $this->IllegalBuffer;
        }
        $data = $result;
        return $data;
    }
    //进行数据获取
    protected function getDecrptdData($url)
    {
        $encryptedData=  input('encryptedData');//加密数据
        $iv = input('iv');

        $result = $this->curl($url);
        $result = (new kbxToken())->object_array($result);
        if(isset($result['errcode'])) return ['',$result];
        //获取session_key
        $sessionKey = $result['session_key'];
        //获取解密数据
        /**
         * {session_key:'xxx',openid:'xxx',unionid:'xxx'}
         */
        $decryptData = $this->decryptData($encryptedData, $iv, $data, $this->appid, $sessionKey);
        $decryptDataArr = json_decode($decryptData,'true');

        return [$sessionKey,$decryptDataArr];
    }
    //远程获取接口信息
    protected function curl($url)
    {
        // 1. 初始化一个cURL会话
        $ch = curl_init();
        // 2. 设置请求选项, 包括具体的url
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        // 3. 执行一个cURL会话并且获取相关回复
        $response = curl_exec($ch);
        // 4. 释放cURL句柄,关闭一个cURL会话
        curl_close($ch);

        return json_decode($response);
    }

    //获取用户手机号
    public function getUserPhone()
    {
        $wxsoft = input('wxsoft','beimei');
        if($wxsoft=='grouptour'){//拼游
            $wxsoft_config = $this->getTourInfo();
        }else{
            $wxsoft_config = $this->getBeimeiInfo();
        }
        $this->appid = $wxsoft_config['appid'];
        $this->appsecret = $wxsoft_config['secret'];
        $encryptedData = urldecode(input('encryptedData'));//加密数据
//        $encryptedData = input('encryptedData');//加密数据
        $iv = input('iv');
        $sessionKey = input('sessionKey');
        //获取用户身份
        $unionid = input('unionId');
        $member = db("member")->where('wechat_unionid',$unionid)->find();
        if(empty($unionid) || empty($member)) return json_encode(['code'=>101,'msg'=>'请先授权']);


        $decryptData= $this->decryptData($encryptedData, $iv, $data, $this->appid, $sessionKey);;
        $decryptDataArr = json_decode($decryptData,'true');
        if(!is_array($decryptDataArr)){
            return json_encode(['code'=>$decryptDataArr,'msg'=>'获取手机号信息失败']);
        }
        //绑定用户的手机号
        if(empty($member['member_phone'])){
            $userphone = '+'.$decryptDataArr['countryCode'].$decryptDataArr['phoneNumber'];
            db('member')->where('member_id',$member['member_id'])->update(['member_phone'=>$userphone]);
            $updateData = [
              'username'=>$userphone,
              'wechat'=>[
                  'unionidOA'=>$unionid
              ]
            ];
            $this->syncUserDataToOrderSystem($member['member_id'],$updateData);
        }
        //去除多余信息
        unset($decryptDataArr['watermark']);
        return json_encode([
           'code'=>0,
           'msg'=>'获取手机号信息成功',
           'data'=>$decryptDataArr
        ]);
    }

    //刷新用户的token
    protected function updateUserToken($member_id,$token_name='beimei_token')
    {
        $userToken = md5(time().$member_id);
        $res = db('member')->where('member_id',$member_id)->update([
            $token_name=>$userToken,
            $token_name.'_time'=>time()+7*24*3600
        ]);

        return $res!==false?$userToken:"";
    }

    //刷新userToken
    public function refreshUserToken($token_name='beimei_token')
    {
        $oldUserToken = input('user_token');
        $member = db("member")->where($token_name,$oldUserToken)->find();
        if(empty($oldUserToken) || empty($member)){
            //代表用户未登录，需要重新登陆
            $data = [
                'code'=>-102,
                'msg'=>'请先更新资料！授权失败'
            ];
            return json_encode($data);
        }
        if($member[$token_name.'_time'] < time()){//新刷取token
            $newUserToken = $this->updateUserToken($member['member_id'],$token_name);
            if(empty($newUserToken)){
                $data = [
                    'code'=>-101,
                    'msg'=>'获取userToken失败！ 授权失败'
                ];
                return json_encode($data);
            }
        }else{
            $newUserToken = $oldUserToken;
        }

        $data = [
            'code'=>200,
            'msg'=>'授权成功',
            'data'=>[
                'userToken'=>$newUserToken
            ]
        ];
        return json_encode($data);

    }

    //通过微信用户的id和产品id生成小程序二维码并保存到后端
    public function getPromotionQrcode()
    {
        $member_id = input('member_id',0);
        $tour_id = input('tour_id',0);
        $wxsoft = input('wxsoft','grouptour');
        $wx_path = input('wxpath','pages/buy/index');
        if(empty($member_id)) return json_encode(['code'=>-400,'msg'=>'缺少用户id']);
        if(empty($tour_id)) return json_encode(['code'=>-400,'msg'=>'缺少产品id']);
        $spread_code = $tour_id.'-'.$member_id;
        $qrcode = Cache::get($wxsoft.'_wx_spread_'.$spread_code);
        if(!empty($qrcode)){
            $qrcode = (new GT())->replaceOssImgDomain($qrcode);
            return json_encode(['code'=>200,'msg'=>'推广二维码获取成功','data'=>[
                'qrcode'=>$qrcode,
                'path'=>$wx_path,
                'spread_code'=>$spread_code
            ]]);
        }
        $access_token = $this->get_wx_access_token($wxsoft);
        $url = "https://api.weixin.qq.com/wxa/getwxacode?access_token=".$access_token; //$access_token为自己获取的token，后面有写
        $array_json = json_encode([
            'path'=>$wx_path.'?spread_code='.$spread_code,
            'width'=>150,
            'is_hyaline'=>$this->isHyaline
        ]);
        $codeinfo = (new Common())->http($url,"POST", $array_json);//图片流 buffer  curl提交数据 获取图片流
        //判断是否是 json格式
        if(is_null(json_decode($codeinfo))){
            $base64 = base64_encode($codeinfo);
            $img_source =  'data:image/png;base64,' . $base64;
            //上传到OSS
            $result = (new OssController())->base64ToOss($img_source);
            if(!is_array($result)){
                return json_encode(['code'=>-400,'msg'=>$result]);
            }else{
                $qrcode = str_replace('http','https',$result['url']);
                Cache::set($wxsoft.'_wx_spread_'.$spread_code,$qrcode,24*3600);
                $qrcode = (new GT())->replaceOssImgDomain($qrcode);
                return json_encode(['code'=>200,'msg'=>'推广二维码获取成功','data'=>[
                    'qrcode'=>$qrcode,
                    'path'=>$wx_path,
                    'spread_code'=>$spread_code
                ]]);
            }
        }else{
            return $codeinfo;
        }
    }

    //通过产品id生成小程序二维码并保存到后端
    public function getProductPromotionQrcode()
    {
        $tour_id = input('id',0);
        $wxsoft = input('wxsoft','grouptour');
        $wx_path = input('wxpath','pages/buy/index');
        if(empty($tour_id)) return json_encode(['code'=>-400,'msg'=>'缺少产品id']);
        $spread_code = $tour_id;
        $qrcode = Cache::get($wxsoft.'_wx_spread_pid_'.$spread_code);
        if(!empty($qrcode)){
            $qrcode = (new GT())->replaceOssImgDomain($qrcode);
            return json_encode(['code'=>200,'msg'=>'推广二维码获取成功','data'=>[
                'qrcode'=>$qrcode,
                'path'=>$wx_path,
                'spread_code'=>$spread_code
            ]]);
        }
        $access_token = $this->get_wx_access_token($wxsoft);
        $url = "https://api.weixin.qq.com/wxa/getwxacode?access_token=".$access_token; //$access_token为自己获取的token，后面有写
        $array_json = json_encode([
            'path'=>$wx_path.'?spread_code='.$spread_code,
            'width'=>150,
            'is_hyaline'=>$this->isHyaline
        ]);
        $codeinfo = (new Common())->http($url,"POST", $array_json);//图片流 buffer  curl提交数据 获取图片流
        //判断是否是 json格式
        if(is_null(json_decode($codeinfo))){
            $base64 = base64_encode($codeinfo);
            $img_source =  'data:image/png;base64,' . $base64;
            //上传到OSS
            $result = (new OssController())->base64ToOss($img_source);
            if(!is_array($result)){
                return json_encode(['code'=>-400,'msg'=>$result]);
            }else{
                $qrcode = str_replace('http','https',$result['url']);
                Cache::set($wxsoft.'_wx_spread_pid_'.$spread_code,$qrcode,24*3600);
                $qrcode = (new GT())->replaceOssImgDomain($qrcode);
                return json_encode(['code'=>200,'msg'=>'推广二维码获取成功','data'=>[
                    'qrcode'=>$qrcode,
                    'path'=>$wx_path,
                    'spread_code'=>$spread_code
                ]]);
            }
        }else{
            return $codeinfo;
        }
    }
    //同步生产站的微信access_token
    public function get_wx_access_token($wxsoft='grouptour'){
        if(!empty($access_token)) return $access_token;
        $url = "https://c.kuaibangxing.com/api/unionid/get_wx_access_token?wxsoft=".$wxsoft;
        $access_token = $this->wxCurl($url);
        return $access_token;
    }

    //远程获取资源
    public function wxCurl($url)
    {
        //初始化
        $curl = curl_init();
        //设置抓取的url
        curl_setopt($curl, CURLOPT_URL, $url);
        //设置头文件的信息作为数据流输出
        curl_setopt($curl, CURLOPT_HEADER, 0);
        //设置获取的信息以文件流的形式返回，而不是直接输出。
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        //执行命令
        $data = curl_exec($curl);
        //关闭URL请求
        curl_close($curl);

        return $data;
    }

    //同步客户信息到订单系统
    public function syncUserDataToOrderSystem($member_id,$updateDate)
    {
        //与订单系统同步客户信息
        $content =  (new MApi())->kbxUserUpdate($updateDate);
        //返沪数据 且无msg错误信息 有订单系统的id
        if(!empty($content) && !empty($content['id']) && empty($content['msg'])){
            $member = db('member')->find($member_id);
            if(!empty($member)){
                if(empty($member['kbx_id']) || $member['kbx_id']!=$content['id']){
                    $res = db('member')->where('member_id',$member_id)->update(['kbx_id'=>$content['id']]);
                }
            }
        }

        trace("同步账号信息：".json_encode($updateDate));
        trace("同步账号结果：".json_encode($content));
        return $res??false;
    }

    //微信小程序订阅消息
    public function sendSubscribeMessage($openid="",$template_id="",$info=[],$wxsoft='grouptour',$page='')
    {
        if(empty($openid)) return "缺少openid";
        if(empty($template_id)) return "缺少template_id";
        $access_token = $this->get_wx_access_token($wxsoft);
        $url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=".$access_token;
        $post_data['touser'] = $openid;
        $post_data['template_id'] = $template_id;
        $post_data['page'] = $page;
        foreach ($info as $key=>$value){
            $post_data['data'][$key]['value'] = $value;
        }
        $post_data = json_encode($post_data);
        $result = (new Common())->http($url,"POST", $post_data);
        $result = json_decode($result,true);
        //记录错误信息
        trace(json_encode($result));
        if($result['errcode']>0){
            return $result['errcode'].':'.$result['errmsg'];
        }else{
            return $result;
        }
    }
    //发送拼团的订阅消息
    public function sendGroupTourDataToSubscribeMessage($order_no,$member_id,$info)
    {
        $memberInfo = db('member')->find($member_id);
        if(empty($memberInfo['grouptour_openid'])) return [];
        $openid = $memberInfo['grouptour_openid'];
        $template_id='-V_SaTZ1X8G18ekAuQkgeT-Ce49LazdiT10u6Db_gd8';
        if(empty($info)) return [];
        $page = 'pages/buy/pay-order?order_no='.$order_no.'&detail=true';
        $result = $this->sendSubscribeMessage($openid,$template_id,$info,'grouptour',$page);
        if(!is_array($result)){
            return $result;
        }else{
            return ['code'=>200,'msg'=>'success','data'=>$result];
        }
    }
    //发送拼游的订阅消息
    public function sendFreeGroupDataToSubscribeMessage($free_group_id,$member_id,$msg_type)
    {
        $memberInfo = db('member')->find($member_id);
        if(empty($memberInfo['grouptour_openid'])) return [];
        $openid = $memberInfo['grouptour_openid'];
        $template_id='-V_SaTZ1X8G18ekAuQkgeT-Ce49LazdiT10u6Db_gd8';
        $info = $this->getSendDataFreeGroupMsgType($msg_type,$free_group_id);
        if(empty($info)) return [];
        $page = 'pages/freedom/detail?id='.$free_group_id;
        $result = $this->sendSubscribeMessage($openid,$template_id,$info,'grouptour',$page);
        if(!is_array($result)){
            return $result;
        }else{
            return ['code'=>200,'msg'=>'success','data'=>$result];
        }
    }

    //订阅消息类型设置
    public function getSendDataFreeGroupMsgType($msg_type,$free_group_id)
    {
        $freeGroupInfo = db('free_group')->find($free_group_id);
        if(empty($freeGroupInfo)) return [];
        switch ($msg_type){
            case 1://发起拼团 发起人
                $title = "发起拼游成功通知";
                $content = '您已成功发起拼游，当前参与人数'.$freeGroupInfo['cur_people_num'].'人';break;
            case 11://加入拼团 发起人
                $title = "加入拼游成功通知";
                $content = '有新的小伙伴加入拼游,当前参与人数'.$freeGroupInfo['cur_people_num'].'人';break;
            case 12://加入拼团 参与人
                $title = "加入拼游成功通知";
                $content = '您已成功加入拼游，当前参与人数'.$freeGroupInfo['cur_people_num'].'人';break;
            case 21://发起人取消拼团 发起人
                $title = "退出拼游成功通知";
                $content = '您已成功退出拼游';break;
            case 22://发起人取消拼团 参与人
                $title = "退出拼游成功通知";
                $content = '因发起人退出拼游,您已退出拼游';break;
            case 23://参与人取消拼团 发起人
                $title = "退出拼游成功通知";
                $content = '有小伙伴退出拼游,当前参与人数'.$freeGroupInfo['cur_people_num'].'人';break;
            case 24://参与人取消拼团 参与人
                $title = "退出拼游成功通知";
                $content = '您已成功退出拼游';break;
            default:
                $title = $content = "";break;
        }

        return ['thing1'=>$title,'thing2'=>$content];
    }

    //测试订阅消息
    public function sendTest()
    {
        $post = request()->post();
        $openid = $post['openid'];
        $template_id='-V_SaTZ1X8G18ekAuQkgeT-Ce49LazdiT10u6Db_gd8';
        $info=[
            'thing1'=>'支付成功通知',
            'thing2'=>'您已成功加入拼团',
        ];
        $page='';
        $result = $this->sendSubscribeMessage($openid,$template_id,$info,'grouptour',$page);
        return json_encode($result);
    }
}